package com.hhd.flow.engine.impl;

import com.alibaba.fastjson.JSONObject;
import com.hhd.flow.engine.FlowEngine;
import com.hhd.flow.engine.cmd.*;
import com.hhd.flow.engine.cmd.impl.*;
import com.hhd.flow.engine.cmd.impl.virtual.VirtualCompleteUserTaskCommand;
import com.hhd.flow.engine.cmd.impl.virtual.VirtualStartCommand;
import com.hhd.flow.engine.lisener.FlowProcessEventMultiCaster;
import com.hhd.flow.engine.lisener.event.*;
import com.hhd.flow.engine.lisener.impl.DefaultFlowProcessEventMultiCaster;
import com.hhd.flow.engine.res.FlowResourceLoader;
import com.hhd.flow.engine.support.AttachMentType;
import com.hhd.flow.engine.support.FlowEngineSupport;
import com.hhd.flow.engine.support.FlowResource;
import com.hhd.flow.engine.variable.FlowVariableLoader;
import com.hhd.flow.engine.variable.FlowVariablesContainer;
import com.hhd.flow.engine.vo.FlowUser;
import com.hhd.flow.engine.vo.UserTask;
import com.hhd.flow.entity.FlowAttachment;
import com.hhd.flow.entity.FlowProcessInstance;
import com.hhd.flow.service.*;
import com.tang.script.ScriptCommand;
import com.tang.script.ScriptEngine;
import com.tang.script.SystemVariableContainer;
import com.tang.script.command.ScriptCommandBuilder;
import com.tang.script.result.ScriptResult;
import lombok.Getter;
import lombok.Setter;

import javax.script.CompiledScript;
import java.util.List;

@Getter
@Setter
public abstract class AbstractFlowEngine implements FlowEngine {
    FlowResourceLoader flowResourceLoader;
    FlowCommandExecutor flowCommandExecutor;
    FlowCommandBuilder flowCommandBuilder;
    FlowProcessEventMultiCaster flowProcessEventMultiCaster;
    FlowVariableLoader flowVariableLoader;
    ScriptEngine scriptEngine;
    FlowEngineSupport flowEngineSupport;
    SystemVariableContainer systemVariableContainer;

    public <T> CommandResult<T> execute(Command<T> command) {
        return flowCommandExecutor.execute(command);
    }

    public StartProcessCommand.StartProcessCommandBuilder newStartProcessCommandBuilder() {
        return flowCommandBuilder.newStartProcessCommandBuilder();
    }

    public CompleteUserTaskCommand.CompleteUserTaskCommandBuilder newCompleteUserTaskCommandBuilder() {
        return flowCommandBuilder.newCompleteUserTaskCommandBuilder();
    }

    public AddNotifyCommand.AddNotifyCommandBuilder newAddNotifyCommandBuilder() {
        return flowCommandBuilder.newAddNotifyCommandBuilder();
    }

    public CompleteNotifyCommand.CompleteNotifyCommandBuilder newCompleteNotifyCommandBuilder() {
        return getFlowCommandBuilder().newCompleteNotifyCommandBuilder();
    }

    public ToFormCommand.ToFormCommandBuilder newToFormCommandBuilder() {
        return getFlowCommandBuilder().newToFormCommandBuilder();
    }

    public EndCommand.EndCommandBuilder newEndCommandBuilder() {
        return getFlowCommandBuilder().newEndCommandBuilder();
    }

    public CountUserSignCommand.CountUserSignCommandBuilder newCountUserSignCommandBuilder() {
        return flowCommandBuilder.newCountUserSignCommandBuilder();
    }

    public QuerySubtractAbleUserSignCommand.QuerySubtractAbleUserSignCommandBuilder newQuerySubtractAbleUserSignCommandBuilder() {
        return getFlowCommandBuilder().newQuerySubtractAbleUserSignCommandBuilder();
    }

    public SubtractUserSignCommand.SubtractUserSignCommandBuilder newSubtractUserSignCommandBuilder() {
        return getFlowCommandBuilder().newSubtractUserSignCommandBuilder();
    }

    public IFlowAttachmentService getFlowAttachmentService() {
        return flowResourceLoader.getFlowAttachmentService();
    }

    public IFlowCommentService getFlowCommentService() {
        return flowResourceLoader.getFlowCommentService();
    }

    public IFlowGatewayExecutionService getFlowGatewayExecutionService() {
        return flowResourceLoader.getFlowGatewayExecutionService();
    }

    public IFlowPathService getFlowPathService() {
        return flowResourceLoader.getFlowPathService();
    }

    public IFlowProcessDefinitionRefService getFlowProcessDefinitionRefService() {
        return flowResourceLoader.getFlowProcessDefinitionRefService();
    }

    public IFlowProcessDefinitionService getFlowProcessDefinitionService() {
        return flowResourceLoader.getFlowProcessDefinitionService();
    }

    public IFlowProcessInstanceHistoryService getFlowProcessInstanceHistoryService() {
        return flowResourceLoader.getFlowProcessInstanceHistoryService();
    }

    public IFlowProcessInstanceService getFlowProcessInstanceService() {
        return flowResourceLoader.getFlowProcessInstanceService();
    }

    public IFlowTaskHistoryService getFlowTaskHistoryService() {
        return flowResourceLoader.getFlowTaskHistoryService();
    }

    public IFlowTaskService getFlowTaskService() {
        return flowResourceLoader.getFlowTaskService();
    }

    public IFlowUserTaskHistoryService getFlowUserTaskHistoryService() {
        return flowResourceLoader.getFlowUserTaskHistoryService();
    }

    public IFlowUserTaskService getFlowUserTaskService() {
        return flowResourceLoader.getFlowUserTaskService();
    }

    public <T> ScriptResult<T> executeScript(ScriptCommand<T> script) {
        return scriptEngine.executeScript(script);
    }

    public ScriptCommandBuilder getScriptCommandBuilder() {
        return scriptEngine.getScriptCommandBuilder();
    }

    public void setScriptCommandBuilder(ScriptCommandBuilder scriptCommandBuilder) {
        scriptEngine.setScriptCommandBuilder(scriptCommandBuilder);
    }

    public CompiledScript getScript(String key, String scriptText) {
        return scriptEngine.getScript(key, scriptText);
    }

    public Object loadFunction(String functionName) {
        return scriptEngine.loadFunction(functionName);
    }

    public FlowVariablesContainer loadVariables(String formTypeId, String formId, FlowProcessInstance processInstance) {
        return flowVariableLoader.loadVariables(formTypeId, formId, processInstance);
    }

    public List<FlowUser> loadFlowUser(String formTypeId, String formId, UserTask userTask, PassTaskContext context) {
        return getFlowEngineSupport().loadFlowUser(formTypeId, formId, userTask, context);
    }

    public FlowUser getCurrentUser() {
        return getFlowEngineSupport().getCurrentUser();
    }

    public IFlowUserDoneService getFlowUserDoneService() {
        return getFlowResourceLoader().getFlowUserDoneService();
    }

    public void onStartProcessBefore(StartProcessBeforeEvent event) {
        getFlowProcessEventMultiCaster().onStartProcessBefore(event);
    }

    public void onStartProcessAfter(StartProcessAfterEvent event) {
        getFlowProcessEventMultiCaster().onStartProcessAfter(event);
    }

    public void onBeforeEnterUserTask(BeforeEnterUserTaskEvent event) {
        getFlowProcessEventMultiCaster().onBeforeEnterUserTask(event);
    }

    public void onAfterEnterUserTask(AfterEnterUserTaskEvent event) {
        getFlowProcessEventMultiCaster().onAfterEnterUserTask(event);
    }

    public void onUserTaskBeforeComplete(UserTaskCompleteEvent event) {
        getFlowProcessEventMultiCaster().onUserTaskBeforeComplete(event);
    }

    public void onUserTaskAfterComplete(UserTaskCompleteEvent event) {
        getFlowProcessEventMultiCaster().onUserTaskAfterComplete(event);
    }

    public void onUserTaskCompleteBeforeEvery(UserTaskCompleteEveryEvent event) {
        getFlowProcessEventMultiCaster().onUserTaskCompleteBeforeEvery(event);
    }

    public void onUserTaskCompleteAfterEvery(UserTaskCompleteEveryEvent event) {
        getFlowProcessEventMultiCaster().onUserTaskCompleteAfterEvery(event);
    }

    public void onProcessBeforeApproved(ProcessApprovedEvent event) {
        getFlowProcessEventMultiCaster().onProcessBeforeApproved(event);
    }

    public void onProcessAfterApproved(ProcessApprovedEvent event) {
        getFlowProcessEventMultiCaster().onProcessAfterApproved(event);
    }

    public void onFlowUserTaskBeforeEnd(FlowUserTaskEndEvent event) {
        getFlowProcessEventMultiCaster().onFlowUserTaskBeforeEnd(event);
    }

    public void onFlowUserTaskAfterEnd(FlowUserTaskEndEvent event) {
        getFlowProcessEventMultiCaster().onFlowUserTaskAfterEnd(event);
    }

    public void onFlowUserTaskBeforeToForm(FlowUserTaskToFormEvent event) {
        getFlowProcessEventMultiCaster().onFlowUserTaskBeforeToForm(event);
    }

    public void onFlowUserTaskAfterToForm(FlowUserTaskToFormEvent event) {
        getFlowProcessEventMultiCaster().onFlowUserTaskAfterToForm(event);
    }

    public void onEnterNode(EnterNodeEvent event) {
        getFlowProcessEventMultiCaster().onEnterNode(event);
    }

    public void onPassNode(PassNodeEvent event) {
        getFlowProcessEventMultiCaster().onPassNode(event);
    }

    public void onProcessBeforeFinish(ProcessFinishEvent event) {
        getFlowProcessEventMultiCaster().onProcessBeforeFinish(event);
    }

    public void onProcessAfterFinish(ProcessFinishEvent event) {
        getFlowProcessEventMultiCaster().onProcessAfterFinish(event);
    }

    public void onCreateUserTaskEvent(CreateUserTaskEvent event) {
        flowProcessEventMultiCaster.onCreateUserTaskEvent(event);
    }

    public FlowVariablesContainer loadVariableContainerForDefinition(String formTypeId, String formId, FlowProcessInstance processInstance) {
        return getFlowVariableLoader().loadVariableContainerForDefinition(formTypeId, formId, processInstance);
    }

    public List<DefaultFlowProcessEventMultiCaster.ParsedLisener> getParsedLiseners() {
        return flowProcessEventMultiCaster.getParsedLiseners();
    }

    public VirtualStartCommand.VirtualStartCommandBuilder newVirtualStartCommandBuilder() {
        return getFlowCommandBuilder().newVirtualStartCommandBuilder();
    }

    public VirtualCompleteUserTaskCommand.VirtualCompleteUserTaskCommandBuilder newVirtualCompleteUserTaskCommandBuilder() {
        return getFlowCommandBuilder().newVirtualCompleteUserTaskCommandBuilder();
    }

    public FlowAttachment upload(FlowResource resource, AttachMentType attachMentType) {
        return flowEngineSupport.upload(resource, attachMentType);
    }

    public FlowResource loadResource(FlowAttachment attachment) {
        return flowEngineSupport.loadResource(attachment);
    }

    public FlowUser getFlowUserById(String userId) {
        return flowEngineSupport.getFlowUserById(userId);
    }

    public QueryNotifyFlowUserCommand.QueryNotifyFlowUserCommandBuilder newQueryNotifyFlowUserCommandBuilder() {
        return flowCommandBuilder.newQueryNotifyFlowUserCommandBuilder();
    }

    public FlowVariablesContainer convertJSONToFormModel(String formTypeId, String formId, FlowProcessInstance processInstance, JSONObject formModel) {
        return getFlowVariableLoader().convertJSONToFormModel(formTypeId, formId, processInstance, formModel);
    }

    public String getCurrentUserSign() {
        return getFlowEngineSupport().getCurrentUserSign();
    }

    public FlowResource loadUserSign(String userSign) {
        return getFlowEngineSupport().loadUserSign(userSign);
    }

    public void onBeforeWithdraw(WithdrawEvent event) {
        getFlowProcessEventMultiCaster().onBeforeWithdraw(event);
    }

    public void onAfterWithdraw(WithdrawEvent event) {
        getFlowProcessEventMultiCaster().onAfterWithdraw(event);
    }

    public WithdrawCommand.WithdrawCommandBuilder newWithdrawCommandBuilder() {
        return getFlowCommandBuilder().newWithdrawCommandBuilder();
    }

    @Override
    public IFlowActionLogService getFlowActionLogService() {
        return getFlowResourceLoader().getFlowActionLogService();
    }

    @Override
    public ToFormByAdminCommand.ToFormByAdminCommandBuilder newToFormByAdminCommandBuilder() {
        return flowCommandBuilder.newToFormByAdminCommandBuilder();
    }

    @Override
    public RetrieveUserTaskCommand.RetrieveUserTaskCommandBuilder newRetrieveUserTaskCommandBuilder() {
        return flowCommandBuilder.newRetrieveUserTaskCommandBuilder();
    }


}
